; DCHECK v1.00 - DUPCHECK two better - by ESKAY
;
cr	equ	0dh
lf	equ	0ah
;
.z80
.request syslib
;
start:	ld	sp,stack
	call	print##
	cr,lf,lf,lf
	'              ------------------------------------------------',cr,lf
	'             | DCHECK v1.00        22 Jun 85         by ESKAY |',cr,lf
	'             | Disk Check Program displays missing and double |',cr,lf
	'             | allocation  blocks  and  affected  file names. |',cr,lf
	'              ------------------------------------------------'
	cr,lf,lf,0
	ld	a,(5ch)
	or	a
	jr	nz,havdrv
	call	print##
	'ERROR: no drive specified',cr,lf,7,0
	rst	0
;
havdrv:	ld	c,14		; select the drive
	ld	e,a
	dec	e
	call	bdos##
	ld	c,19
	call	50h		; return alloc info
	cp	0ffh
	jr	nz,netok
	call	print##
	'Network error',7,cr,lf,0
	rst	0
;
netok:	ld	a,h
	or	a
	jr	nz,alocok
	call	print##
	'ERROR: cannot process small drives',cr,lf,7,0
	rst	0
;
alocok:	call	print##
	'Loading allocation map...',cr,lf,0
	call	codend##
	ld	(bitmap),hl
	push	hl
	pop	ix
	ld	bc,4000h
..zl:	ld	(hl),0
	inc	hl
	dec	bc
	ld	a,b
	or	c
	jr	nz,..zl
	ld	de,dirfcb
	call	f$open##
rlp:	call	f$read##
	ld	iy,80h
..rl1:	ld	a,(iy+15)
	cp	0ffh			; dirlbl?
	jr	z,..sklb		;   yes
	cp	0feh			; bitmap?
	jr	nz,endmap		;   no, end of map
	inc	iy
	ld	ix,(bitmap)
	ld	b,14			; 14 bytes to move
	call	movxy
	inc	iy
	ld	b,16
	call	movxy
	ld	a,(iy)
	cp	0e5h
	ld	(bitmap),ix
	jr	z,..rl1
	jr	rlp
;
..sklb:	ld	iy,0a0h
	jr	..rl1
;

movxy:	ld	a,(iy)
	ld	(ix),a
	inc	ix
	inc	iy
	djnz	movxy
	ret
;
; bit map read into ram
;
endmap:	push	ix
	pop	hl
	ld	l,0
	inc	h
	ld	(newmap),hl
	ld	de,dirfcb
	call	f$close##
	call	print##
	'Checking for unallocated blocks...',cr,lf,0
	ld	a,'?'
	ld	(dirfcb),a
	call	codend##
	ld	(bitmap),hl
	ld	de,dirfcb
	ld	c,17
	call	bdos##
loop:	ld	de,dirfcb
	ld	c,18
	call	bdos##
	cp	0ffh
	jp	z,done
	ld	b,a
	or	a
	jr	nz,..ski
	ld	hl,(testc)
	inc	hl
	ld	(testc),hl
..ski:	inc	b
	ld	a,80h
	ld	c,20h
..c:	dec	b
	jr	z,..dn
	add	a,c
	jr	..c
..dn:	ld	l,a
	ld	h,0
	ld	a,(hl)
	cp	0e5h
	jr	z,loop
	push	hl
	push	hl
	pop	hl
	ld	(fnptr),hl
	pop	de
	ld	b,8
	ld	de,10h
	add	hl,de
..ram:	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	a,d
	or	e
	jr	nz,..ram1
	djnz	..ram
	jr	..ramq
;
..ram1:	ex	de,hl
	push	de
	push	bc
	call	bitchk
	pop	bc
	pop	hl
	djnz	..ram
..ramq:	xor	a
	ld	(noprev),a
	ld	(double),a
	jp	loop
;
bitchk:	ld	(blocka),hl
	call	bitclc
	ld	b,a
	inc	b
	ld	a,1
..bitc:	dec	b
	jr	z,..bitd
	add	a,a
	jr	..bitc
;
..bitd:	ld	de,(newmap)
	push	hl
	add	hl,de
	ld	b,a
	ld	a,(hl)
	and	b
	call	nz,barfdb		; double alloc
	ld	a,b
	or	(hl)
	ld	(hl),a
	pop	hl
	ld	de,(bitmap)
	add	hl,de
	ld	a,(hl)
	and	b
	ret	nz
	ld	a,1
	ld	(noprev),a
	push	de
	push	hl
	ld	hl,(blocka)
	call	print##
	cr,lf
	'Unallocated block # ',0
	call	phl4hc##
	call	print##
	' in file ',0
	ld	de,(fnptr)
	ld	a,(de)
	inc	de
	call	pafdc##
	ld	c,25
	call	bdos##
	add	a,'A'
	call	cout##
	ld	a,':'
	call	cout##
	call	pfn1##
	pop	hl
	pop	de
	ret
;
barfdb:	ld	a,1
	ld	(double),a
	push	de
	push	hl
	ld	de,(blocka)
	ld	hl,(dptr)
	ld	(hl),e
	inc	hl
	ld	(hl),d
	inc	hl
	ld	(dptr),hl
	ld	hl,dnum
	inc	(hl)
	pop	hl
	pop	de
	ret
;
done:	ld	a,(dnum)
	or	a
	jr	nz,dodbls
	call	print##
	cr,lf
	'No duplicate blocks found.',cr,lf,lf,0
	rst	0
;
; go through directory again (with sfirst/snext) and display
; names of all files and the allocation block address in
; question if it is a multiple.
;
dodbls:	call	print##
	cr,lf
	'Checking for multiple allocation blocks...',cr,lf,0
	ld	de,dirfcb
	ld	c,17
	call	bdos##		; swallow dir label
dodlp:	ld	de,dirfcb
	ld	c,18
	call	bdos##
	cp	0ffh
	jp	z,finish
	ld	b,a
	inc	b
	ld	a,80h
	ld	c,20h
..c1:	dec	b
	jr	z,..dn1
	add	a,c
	jr	..c1
;
..dn1:	ld	l,a
	ld	h,0
	ld	a,(hl)
	cp	0e5h		; erased?
	jr	z,dodlp		;   yes, do next
	push	hl		; save filename ptr
	ld	de,16
	add	hl,de		; point to allocation blocks
	ld	b,8		; up to 8 to check
alckl:	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	call	chkdup		; check if it's a dupe
	jr	c,isdp		;   if it is, show filename
	djnz	alckl
	pop	hl
	jr	dodlp
;
isdp:	call	print##
	cr,lf
	'Multiple alloc : ',0
	pop	de		; get filename ptr
	push	de
	ld	a,(de)		; get user area
	cp	10
	jr	nc,..nt10
	ld	a,' '
	call	cout##
..nt10:	ld	a,(de)
	inc	de
	call	pafdc##
	ld	c,25
	call	bdos##
	add	a,'A'
	call	cout##
	ld	a,':'
	call	cout##
	call	pfn1##
	call	print##
	'  -  ',7,0
	pop	hl
	ld	de,16
	add	hl,de
	ld	b,8
..dall:	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ld	a,d
	or	e
	jp	z,dodlp
	ex	de,hl
	call	phl4hc##
	ex	de,hl
	ld	a,' '
	call	cout##
	djnz	..dall
	jp	dodlp
;
; check for duplicate, preserve hl,de,bc
;
chkdup:	push	hl
	push	de
	push	bc
	ld	a,d
	or	e
	jr	z,chkdux
	ld	hl,doubla	; pointer to list
	ld	a,(dnum)	; length of list in words
	ld	b,a		; counter
chkdu1:	ld	a,(hl)
	inc	hl
	cp	e
	jr	z,chkdum
	inc	hl
	jr	chkdu2
;
chkdum:	ld	a,(hl)
	inc	hl
	cp	d
	jr	z,chkduf
chkdu2:	djnz	chkdu1
	xor	a
	jr	chkdux
;
chkduf:	scf
chkdux:	pop	bc
	pop	de
	pop	hl
	ret
;
; this routine is passed a bitmap address in HL.
; In HL, the relative byte address is returned, A has the bit number.
;
bitclc:	ld	a,l
	and	7
	push	af
	ld	a,l
	and	0f8h
	ld	l,a
	pop	af
	or	a
	srl	h
	rr	l
	srl	h
	rr	l
	srl	h
	rr	l
	ret
;
; done after finding stuff
;
finish:	call	print##
	cr,lf,lf
	'*** AFFECTED BLOCK ADDRESS(ES):',cr,lf,0
	ld	a,(dnum)
	ld	b,a
	ld	hl,doubla
finilp:	ld	e,(hl)
	inc	hl
	ld	d,(hl)
	inc	hl
	ex	de,hl
	ld	a,b
	and	7
	call	z,crlf##
	call	phl4hc##
	ex	de,hl
	call	print
	'  ',0
	djnz	finilp
	call	print##
	cr,lf,lf
	'DCHECK completed - check all multiply allocated files,  then',cr,lf
	'cause everyone to log off.  Delete bad files and IMMEDIATELY',cr,lf
	'execute the FIXMAP command to prevent further damage.',cr,lf,lf,0
	rst	0
;
noprev:	db	0
double:	db	0
lps:	db	20
testc:	dw	0
newmap:	dw	0		; new bitmap
bitmap:	dw	0		; bitmap base
blocka:	dw	0		; block to be tested
dirfcb:	db	0,'$       DIR',0,0,0,0
	ds	22
;
; storage for doubles:
;
dnum:	db	0
dptr:	dw	doubla
doubla:	ds	200		; enough!
;
fnptr:	dw	0
;
	ds	100
stack	equ	$
	end
 bit number.
;
bitclc:	ld	a,l
	and	7
	push	af
	